from PySimpleGUI import cprint
from scapy.all import *
import scapy_http.http
import re
import PySimpleGUI as sg
import threading

obj_http_response = re.compile(r'###\[ HTTP \]###(?P<http>.*?Additional-Headers)', re.S)
# Additional-Headers
# obj = re.compile(r"<a href=\"(?P<href>thread-.*?htm)\"", re.S)
obj_tcp = re.compile(r"")
obj_udp = re.compile(r"")
obj_ip = re.compile(r"")
obj_ethernet = re.compile(r"")
obj_ens_name = re.compile(r"(?P<ens_name>.*?): flags")

flag_stop = 0
flag_end = 0
flag_return = 0
flag_change = 0
iface = ''
filter = ''
protocol = ""
res = os.popen("ifconfig")
ens_list = res.read().split("\n")
input_lst = []
output_lst = []
ens_name_list = []

for i in ens_list:
    if "flags" in i:
        ens_name_list.append(i.split(":")[0])

menu = [
    [' help ']
]

layout_init = [
    [sg.Menu(menu)],
    [sg.T('欢迎使用', font=('Helvetica', 25), size=(100, 0), pad=(0, 30))],
    [sg.T('请选择网卡', font=('Helvetica', 15), size=(250, 1), pad=(0, 10))],
    [sg.LB(ens_name_list, key='ens_lst', font=('Helvetica', 18), size=(250, 20))],
    [sg.B('确定', key='ack_1', font=('Helvetica', 15), size=(10, 1), pad=(550, 15))]
]

layout_protocol = [
    [sg.T('请选择协议类型', font=('Helvetica', 15), size=(250, 1), pad=(0, 10))],
    [sg.LB(['Ethernet', 'IP', 'TCP', 'UDP', 'HTTP'], key='protocol_lst', font=('Helvetica', 18), size=(250, 15))],
    [sg.T('请输入过滤规则，默认为空:', font=('Helvetica', 18), pad=(0, 50)),
     sg.In(key='filter_input', font=('Helvetica', 18), pad=(0, 50))],
    [sg.B('确定', key='ack_2', font=('Helvetica', 15), size=(10, 1), pad=((480, 5), 10)),
     sg.B('返回', key='return_1', font=('Helvetica', 15), size=(10, 1), pad=((5, 0), 10))]
]

layout_show = [
    [sg.B('停止', key='stop', font=('Helvetica', 15), size=(10, 1), pad=((5, 0), 10)),
     sg.B('继续', key='continue', font=('Helvetica', 15), size=(10, 1), pad=((5, 0), 10)),
     sg.B('返回', key='return_2', font=('Helvetica', 15), size=(10, 1), pad=((5, 0), 10))],
    [sg.ML(key='ml', reroute_cprint=True, size=(300, 60), font=('Helvetica', 15))]
]

layout = [
    [sg.Frame(title='', layout=layout_init, key='ens', relief="flat"),
     sg.Frame(title='', layout=layout_protocol, visible=False, key='protocol_frame', relief="flat"),
     sg.Frame(title='', layout=layout_show, visible=False, key='show_frame', relief="flat")
     ]
]

window = sg.Window('w4resh4rk', layout, size=(1200, 800))


def call_back_http(call_back_packet):
    if call_back_packet.haslayer("HTTP"):
        # cprint("=" * 50 + "HTTP数据包:" + 50 * "=")
        cprint("=" * 110)
        cprint("Ethernet dst:", call_back_packet['Ethernet'].dst)
        cprint("Ethernet src:", call_back_packet['Ethernet'].src)
        cprint("Ethernet type:", call_back_packet['Ethernet'].type)
        cprint("IP version:", call_back_packet['IP'].version)
        cprint("IP ihl:", call_back_packet['IP'].ihl)
        cprint("IP tos:", call_back_packet['IP'].tos)
        cprint("IP len:", call_back_packet['IP'].len)
        cprint("IP id:", call_back_packet['IP'].id)
        cprint("IP flags:", call_back_packet['IP'].flags)
        cprint("IP frag:", call_back_packet['IP'].frag)
        cprint("IP ttl:", call_back_packet['IP'].ttl)
        cprint("IP proto:", call_back_packet['IP'].proto)
        cprint("IP chksum:", call_back_packet['IP'].chksum)
        cprint("IP src:", call_back_packet['IP'].src)
        cprint("IP dst:", call_back_packet['IP'].dst)
        cprint("TCP sport:", call_back_packet['TCP'].sport)
        cprint("TCP dport:", call_back_packet['TCP'].dport)
        cprint("TCP seq:", call_back_packet['TCP'].seq)
        cprint("TCP ack:", call_back_packet['TCP'].ack)
        cprint("TCP dataofs:", call_back_packet['TCP'].dataofs)
        cprint("TCP reserved:", call_back_packet['TCP'].reserved)
        cprint("TCP flags:", call_back_packet['TCP'].flags)
        cprint("TCP window:", call_back_packet['TCP'].window)
        cprint("TCP chksum:", call_back_packet['TCP'].chksum)
        cprint("TCP urgptr:", call_back_packet['TCP'].urgptr)
        cprint("TCP options:", call_back_packet['TCP'].options)
        cprint("=" * 110)

        data = str(call_back_packet.show(dump=True))
        # print(data)
        http_it = obj_http_response.finditer(data)
        # print("=" * 50 + "HTTP数据包:")
        for it in http_it:
            # print("HTTP数据:" + it.group("http") + str(type(it.group("http"))))
            http_list = it.group("http").split("\n")
            if "Request" in http_list[1]:
                # print("获取Request包")
                for i in http_list:
                    # print(i)
                    i_list = i.split("=")
                    if len(i_list) < 2:
                        continue
                    i_list[0] = i_list[0].strip()
                    i_list[1] = i_list[1].strip()
                    print("HTTP " + i_list[0] + ":" + i_list[1])
            if "Response" in http_list[1]:
                # print("获取Response包")
                for i in http_list:
                    # print(i)
                    i_list = i.split("=")
                    if len(i_list) < 2:
                        continue
                    i_list[0] = i_list[0].strip()
                    i_list[1] = i_list[1].strip()
                    print("HTTP " + i_list[0] + ":" + i_list[1])


def call_back_udp(call_back_packet):
    if call_back_packet.haslayer("UDP"):
        # cprint("=" * 50 + "UDP数据包:" + 50 * "=")
        cprint("=" * 110)
        cprint("Ethernet dst:", call_back_packet['Ethernet'].dst)
        cprint("Ethernet src:", call_back_packet['Ethernet'].src)
        cprint("Ethernet type:", call_back_packet['Ethernet'].type)
        cprint("IP version:", call_back_packet['IP'].version)
        cprint("IP ihl:", call_back_packet['IP'].ihl)
        cprint("IP tos:", call_back_packet['IP'].tos)
        cprint("IP len:", call_back_packet['IP'].len)
        cprint("IP id:", call_back_packet['IP'].id)
        cprint("IP flags:", call_back_packet['IP'].flags)
        cprint("IP frag:", call_back_packet['IP'].frag)
        cprint("IP ttl:", call_back_packet['IP'].ttl)
        cprint("IP proto:", call_back_packet['IP'].proto)
        cprint("IP chksum:", call_back_packet['IP'].chksum)
        cprint("IP src:", call_back_packet['IP'].src)
        cprint("IP dst:", call_back_packet['IP'].dst)
        cprint("UDP sport:", call_back_packet['UDP'].sport)
        cprint("UDP dport:", call_back_packet['UDP'].dport)
        cprint("UDP len:", call_back_packet['UDP'].len)
        cprint("UDP chksum:", call_back_packet['UDP'].chksum)
        cprint("=" * 110)


def call_back_ethernet(call_back_packet):
    if call_back_packet.haslayer("Ethernet"):
        # cprint("=" * 50 + "以太数据包:" + 50 * "=")
        cprint("=" * 110)
        cprint("Ethernet dst:", call_back_packet['Ethernet'].dst)
        cprint("Ethernet src:", call_back_packet['Ethernet'].src)
        cprint("Ethernet type:", call_back_packet['Ethernet'].type)
        cprint("=" * 110)


def call_back_tcp(call_back_packet):
    if call_back_packet.haslayer("TCP"):
        # cprint("=" * 50 + "TCP数据包:" + 50 * "=")
        cprint("=" * 110)
        cprint("Ethernet dst:", call_back_packet['Ethernet'].dst)
        cprint("Ethernet src:", call_back_packet['Ethernet'].src)
        cprint("Ethernet type:", call_back_packet['Ethernet'].type)
        cprint("IP version:", call_back_packet['IP'].version)
        cprint("IP ihl:", call_back_packet['IP'].ihl)
        cprint("IP tos:", call_back_packet['IP'].tos)
        cprint("IP len:", call_back_packet['IP'].len)
        cprint("IP id:", call_back_packet['IP'].id)
        cprint("IP flags:", call_back_packet['IP'].flags)
        cprint("IP frag:", call_back_packet['IP'].frag)
        cprint("IP ttl:", call_back_packet['IP'].ttl)
        cprint("IP proto:", call_back_packet['IP'].proto)
        cprint("IP chksum:", call_back_packet['IP'].chksum)
        cprint("IP src:", call_back_packet['IP'].src)
        cprint("IP dst:", call_back_packet['IP'].dst)
        cprint("TCP sport:", call_back_packet['TCP'].sport)
        cprint("TCP dport:", call_back_packet['TCP'].dport)
        cprint("TCP seq:", call_back_packet['TCP'].seq)
        cprint("TCP ack:", call_back_packet['TCP'].ack)
        cprint("TCP dataofs:", call_back_packet['TCP'].dataofs)
        cprint("TCP reserved:", call_back_packet['TCP'].reserved)
        cprint("TCP flags:", call_back_packet['TCP'].flags)
        cprint("TCP window:", call_back_packet['TCP'].window)
        cprint("TCP chksum:", call_back_packet['TCP'].chksum)
        cprint("TCP urgptr:", call_back_packet['TCP'].urgptr)
        cprint("TCP options:", call_back_packet['TCP'].options)
        cprint("=" * 110)


def call_back_ip(call_back_packet):
    if call_back_packet.haslayer("TCP"):
        # cprint("=" * 50 + "TCP数据包:" + 50 * "=")
        cprint("=" * 110)
        cprint("Ethernet dst:", call_back_packet['Ethernet'].dst)
        cprint("Ethernet src:", call_back_packet['Ethernet'].src)
        cprint("Ethernet type:", call_back_packet['Ethernet'].type)
        cprint("IP version:", call_back_packet['IP'].version)
        cprint("IP ihl:", call_back_packet['IP'].ihl)
        cprint("IP tos:", call_back_packet['IP'].tos)
        cprint("IP len:", call_back_packet['IP'].len)
        cprint("IP id:", call_back_packet['IP'].id)
        cprint("IP flags:", call_back_packet['IP'].flags)
        cprint("IP frag:", call_back_packet['IP'].frag)
        cprint("IP ttl:", call_back_packet['IP'].ttl)
        cprint("IP proto:", call_back_packet['IP'].proto)
        cprint("IP chksum:", call_back_packet['IP'].chksum)
        cprint("IP src:", call_back_packet['IP'].src)
        cprint("IP dst:", call_back_packet['IP'].dst)
        cprint("=" * 110)


def sniff_data(iface):
    while not flag_end:
        while not flag_change:
            if protocol == 'Ethernet':
                if flag_stop == 0:
                    sniff(filter=filter, prn=call_back_ethernet, iface=iface, count=1)
                    window.Refresh()
            elif protocol == 'IP':
                if flag_stop == 0:
                    sniff(filter=filter, prn=call_back_ip, iface=iface, count=1)
                    window.Refresh()
            elif protocol == 'TCP':
                if flag_stop == 0:
                    sniff(filter=filter, prn=call_back_tcp, iface=iface, count=1)
                    window.Refresh()
            elif protocol == 'UDP':
                if flag_stop == 0:
                    sniff(filter=filter, prn=call_back_udp, iface=iface, count=1)
                    window.Refresh()
            elif protocol == 'HTTP':
                if flag_stop == 0:
                    sniff(filter=filter, prn=call_back_http, iface=iface, count=1)
                    window.Refresh()


while True:
    event, values = window.read()
    if event == None:
        flag_end = 1
        break
    if event == 'ack_1':
        print(f"您选择的网卡是:{window['ens_lst'].get()}")
        try:
            iface_ = window['ens_lst'].get()
            iface = iface_[0]
        except:
            sg.popup_ok('错误', title='提示', modal=True, font=('Helvetica', 15) ,keep_on_top=True)
            continue
        window['ens'].update(visible=False)
        window['protocol_frame'].update(visible=True)
    if event == 'ack_2':
        flag_stop = 0
        print(f"您选择的协议类型是:{window['protocol_lst'].get()}")
        try:
            protocol_ = window['protocol_lst'].get()
            protocol = protocol_[0]
        except:
            sg.popup_ok('错误', title='提示', modal=True, font=('Helvetica', 15) ,keep_on_top=True)
            continue
        window['protocol_frame'].update(visible=False)
        window['show_frame'].update(visible=True)
        print(f"您的过滤规则是:{values['filter_input']}")
        filter = values['filter_input']
        window.Refresh()
        if len(filter) == 0:
            filter = ""

        # protocol = int(input("请输入协议类型:"))
        # filter = "ip"
        # filter = "udp"
        # filter = "host 192.168.88.132 and tcp"
        # filter="ether src host 00:0c:29:3c:d1:44"
        # filter="src host 172.18.249.122"
        # filter="port 80"
        # filter="!port 80"
        # filter="icmp"
        if flag_return == 0:
            thread = threading.Thread(target=sniff_data, args=(iface,))
            thread.setDaemon(True)
            thread.start()
            flag_return = flag_return + 1
        else:
            window['ml'].update(value="", append=False)
            flag_change = 0

    if event == 'return_1':
        window['ens'].update(visible=True)
        window['protocol_frame'].update(visible=False)

    if event == 'return_2':
        flag_stop = 1
        flag_change = 1
        window['protocol_frame'].update(visible=True)
        window['show_frame'].update(visible=False)
        window['ml'].update(value="", append=False)

    if event == 'stop':
        flag_stop = 1
        print('stop')

    if event == 'continue':
        flag_stop = 0
        print('continue')

window.close()
